package com.ap.core.business.message.response.translators.impl;

import java.util.List;

import org.apache.commons.lang.StringUtils;

import com.ap.core.business.message.domain.translators.BindingMetaData;
import com.ap.core.business.message.response.translators.ResponseMetaData;
import com.ap.core.business.message.response.translators.ResponseTranslator;
import com.ap.core.business.message.response.translators.listener.ResponseListener;
import com.ap.core.cxf.jaxb.common.AddressMandatoryCountryCode;
import com.ap.core.cxf.jaxb.common.CurrencyCodeType;
import com.ap.core.cxf.jaxb.common.DeliveryAddressType;
import com.ap.core.cxf.jaxb.common.DeliveryInfoType;
import com.ap.core.cxf.jaxb.common.DeliveryType;
import com.ap.core.cxf.jaxb.common.ResponseStatusType;
import com.ap.core.cxf.jaxb.distributor.DistributorInfoType;
import com.ap.core.cxf.jaxb.managepayment.ConsumerAccountInfoType;
import com.ap.core.cxf.jaxb.managepayment.CreditActType;
import com.ap.core.cxf.jaxb.managepayment.RTPIdentifierType;
import com.ap.core.cxf.jaxb.managepayment.RTPSummaryType;
import com.ap.core.cxf.jaxb.rtp.DetailMerchantInfoType;
import com.ap.core.cxf.jaxb.rtp.DetailedAmtType;
import com.ap.core.cxf.jaxb.rtp.MerchantInfoType;
import com.ap.core.cxf.jaxb.rtp.PaymtAmtInfoType;
import com.ap.core.cxf.jaxb.rtp.ProductType;
import com.ap.core.cxf.jaxb.rtp.RTPDetailType;
import com.ap.core.cxf.jaxb.rtp.RTPSenderInfoType;
import com.ap.core.cxf.jaxb.rtp.TransactionCheckOutType;
import com.ap.core.cxf.jaxb.rtp.TxIdentificationType;
import com.ap.core.dao.DistributorDao;
import com.ap.core.dao.FinancialInstitutionDao;
import com.ap.core.dao.MerchantDao;
import com.ap.core.dao.ZappConsumerUserDao;
import com.ap.core.domain.DeliveryAddress;
import com.ap.core.domain.Distributor;
import com.ap.core.domain.Merchant;
import com.ap.core.domain.OrderAmountDetail;
import com.ap.core.domain.OrderPayment;
import com.ap.core.domain.OrderProductDetail;
import com.ap.core.domain.ZappConsumerUser;
import com.ap.core.message.managepayment.info.RTPForAuthorisationMessageInfo;
import com.ap.core.message.managepayment.info.RetrieveRTPMessageInfo;

/**
 * User: Ranjit.Singh
 * implementation class for {@link com.ap.core.business.message.response.translators.ResponseTranslator} to populate {@link com.ap.core.cxf.jaxb.common.ResponseWithIntentType}  in response object
 */
public class RetrieveRTPResponseTranslator implements ResponseTranslator<RetrieveRTPMessageInfo, RTPForAuthorisationMessageInfo> {

    private DistributorDao distributorDao;
    private MerchantDao merchantDao;
    private FinancialInstitutionDao financialInstitutionDao;
    private ZappConsumerUserDao zappConsumerUserDao;

    /**
     * {@inheritDoc}
     */
    @Override
    public void populateResponse(RetrieveRTPMessageInfo request, RTPForAuthorisationMessageInfo response, BindingMetaData bindingMetaData, ResponseMetaData responseMetaData, ResponseListener responseListener) {
        final OrderPayment originalOrderPayment = responseMetaData.getOriginalReadOnlyOrderPayment();
       
        
        final RTPIdentifierType rtpIdentifierType = new RTPIdentifierType();
        rtpIdentifierType.setApTransactionId(originalOrderPayment.getId());
        rtpIdentifierType.setApTRId(StringUtils.leftPad(String.valueOf(String.valueOf(originalOrderPayment.getApTransactionRetrievalId())),18,"0"));
        
        rtpIdentifierType.setReconId(originalOrderPayment.getReconciliationCycleId());
        rtpIdentifierType.setRTPId(originalOrderPayment.getRtpId());

        final ResponseStatusType responseStatusType = new ResponseStatusType();
        responseStatusType.setResponseCode(responseMetaData.getValidationStatus().getResponseCode());

        rtpIdentifierType.setResponseStatus(responseStatusType);
        response.setRTPIdentifier(rtpIdentifierType);

        final RTPSenderInfoType rtpSenderInfoType = new RTPSenderInfoType();
        final DistributorInfoType distributorInfoType = new DistributorInfoType();
        final Distributor distributor = distributorDao.findById(originalOrderPayment.getDistributorId());

        distributorInfoType.setDistributorId(distributor.getDistributorIdentification());
        distributorInfoType.setDistributorName(distributor.getDistributorName());

        rtpSenderInfoType.setDistributorInfo(distributorInfoType);
        
        

        final DetailMerchantInfoType detailMerchantInfoType = new DetailMerchantInfoType();

        final MerchantInfoType merchantInfoType = new MerchantInfoType();
        final Merchant merchant = merchantDao.findById(originalOrderPayment.getMerchantId());
        merchantInfoType.setMerchantId(merchant.getMerchantIdentification());
        merchantInfoType.setMerchantCmnName(merchant.getCommonName());
        merchantInfoType.setMerchantName(merchant.getName());
        merchantInfoType.setMerchantRtnStrng(originalOrderPayment.getMerchantRedirectURL());

        detailMerchantInfoType.setMerchantInfo(merchantInfoType);

        final AddressMandatoryCountryCode addressMandatoryCountryCode = new AddressMandatoryCountryCode();
        addressMandatoryCountryCode.setAddressLine1(originalOrderPayment.getMerchantAddress().getAddressLine1());
        addressMandatoryCountryCode.setAddressLine2(originalOrderPayment.getMerchantAddress().getAddressLine2());
        addressMandatoryCountryCode.setAddressLine3(originalOrderPayment.getMerchantAddress().getAddressLine3());
        addressMandatoryCountryCode.setAddressLine4(originalOrderPayment.getMerchantAddress().getAddressLine4());
        addressMandatoryCountryCode.setAddressLine5(originalOrderPayment.getMerchantAddress().getAddressLine5());
        addressMandatoryCountryCode.setAddressLine6(originalOrderPayment.getMerchantAddress().getAddressLine6());

        addressMandatoryCountryCode.setPostCode(originalOrderPayment.getMerchantAddress().getPostCode());
        addressMandatoryCountryCode.setCountryCode(originalOrderPayment.getMerchantAddress().getCountryCode());

        detailMerchantInfoType.setMerchantAddress(addressMandatoryCountryCode);

        rtpSenderInfoType.setDetailMerchantInfo(detailMerchantInfoType);


        response.setRTPSenderInfo(rtpSenderInfoType);

        final RTPSummaryType rtpSummaryType = new RTPSummaryType();
        rtpSummaryType.setTxType(originalOrderPayment.getTransactionType());
        rtpSummaryType.setTxCheckout(originalOrderPayment.getTransactionCheckoutType());

        final TxIdentificationType txIdentificationType = new TxIdentificationType();
        txIdentificationType.setTxDtTime(originalOrderPayment.getTransactionTimeStmp());
        txIdentificationType.setRTPId(originalOrderPayment.getRtpId());
        rtpSummaryType.setTxIdentification(txIdentificationType);

        rtpSummaryType.setTxRestriction(null == originalOrderPayment.getTransactionRestrictionType() ? null : originalOrderPayment.getTransactionRestrictionType().getTxRestriction());
        rtpSummaryType.setInvoiceDateTime(originalOrderPayment.getInvoiceTimeStmp());
        rtpSummaryType.setCurrency(CurrencyCodeType.valueOf(originalOrderPayment.getCurrencyCode()));

        final PaymtAmtInfoType paymtAmtInfoType = new PaymtAmtInfoType();
        paymtAmtInfoType.setTotalPaymentReqAmount(originalOrderPayment.getTotalPaymentRequestAmount().getValue());

        final List<DetailedAmtType> detailedAmtTypeList = paymtAmtInfoType.getDetailedAmt();
        for (OrderAmountDetail orderAmountDetail : originalOrderPayment.getOrderAmountDetailList()) {
            final DetailedAmtType detailedAmtType = new DetailedAmtType();
            detailedAmtType.setAmtType(orderAmountDetail.getAmountType());
            detailedAmtType.setAmtValue(orderAmountDetail.getValue().getValue());
            detailedAmtType.setRate(null == orderAmountDetail.getRate()? null : orderAmountDetail.getRate().getValue());
            detailedAmtTypeList.add(detailedAmtType);
        }
        rtpSummaryType.setPaymtAmtInfo(paymtAmtInfoType);
        final CreditActType creditActType = new CreditActType();
        creditActType.setCreditActNum(merchant.getCreditAccountNumber().toString());
        creditActType.setCreditSortCode(merchant.getCreditSortCode().toString());
        rtpSummaryType.setCreditAct(creditActType);

        response.setRTPSummary(rtpSummaryType);

        final RTPDetailType rtpDetailType = new RTPDetailType();

        final List<ProductType> productTypeList = rtpDetailType.getProduct();
        for (OrderProductDetail orderProductDetail : originalOrderPayment.getOrderProductDetailList()) {
            final ProductType productType = new ProductType();
            productType.setProductCode(orderProductDetail.getProductCode());
            productType.setProductDesc(orderProductDetail.getProductDescription());
            productType.setUnitOfMeasure(orderProductDetail.getMeasureUnitCode());
            productType.setProductQuantity(orderProductDetail.getProductQuantity());
            productType.setUnitPrice(orderProductDetail.getUnitPrice().getValue());
            productType.setProductAmount(orderProductDetail.getProductAmount().getValue());
            productType.setAdditionalProductInfo(orderProductDetail.getMiscProductInfo());
            productTypeList.add(productType);
        }
        response.setRTPDetail(rtpDetailType);

        final DeliveryInfoType deliveryInfoType = new DeliveryInfoType();
        deliveryInfoType.setDeliveryType(originalOrderPayment.getDeliveryType());
        final DeliveryAddress deliveryAddress = originalOrderPayment.getDeliveryAddress();
        if (null != deliveryAddress) {
            final DeliveryAddressType manageRTPDeliveryOptionalAddressType = new DeliveryAddressType();
            manageRTPDeliveryOptionalAddressType.setAddressLine1(deliveryAddress.getAddressLine1());
            manageRTPDeliveryOptionalAddressType.setAddressLine2(deliveryAddress.getAddressLine2());
            manageRTPDeliveryOptionalAddressType.setAddressLine3(deliveryAddress.getAddressLine3());
            manageRTPDeliveryOptionalAddressType.setAddressLine4(deliveryAddress.getAddressLine4());
            manageRTPDeliveryOptionalAddressType.setAddressLine5(deliveryAddress.getAddressLine5());
            manageRTPDeliveryOptionalAddressType.setAddressLine6(deliveryAddress.getAddressLine6());

            manageRTPDeliveryOptionalAddressType.setPostCode(deliveryAddress.getPostCode());
            manageRTPDeliveryOptionalAddressType.setCountryCode(deliveryAddress.getCountryCode());
            deliveryInfoType.setDeliveryAddress(manageRTPDeliveryOptionalAddressType);
        }
       
        // Set Zapp User email address, in case of Quick Pay Digital Delivery mcom/ecom.
       
        if(TransactionCheckOutType.QKPACHK.equals(originalOrderPayment.getTransactionCheckoutType())  && DeliveryType.DIGDEL.equals(originalOrderPayment.getDeliveryType())){
        	ZappConsumerUser zappConsumerUser = zappConsumerUserDao.getZappConsumerUserByFiIdentificationAndFiCustomerId(request.getRequestInfo().getFIId(), request.getRequestInfo().getFIConsumerId());
        	deliveryInfoType.setEmailAddress(zappConsumerUser.getZappEmailId());
        }else{
        	deliveryInfoType.setEmailAddress(originalOrderPayment.getEmailAddress());
        }
        	
        
        response.setDelivery(deliveryInfoType);

        final ConsumerAccountInfoType consumerAccountInfoType = new ConsumerAccountInfoType();
        consumerAccountInfoType.setFIConsumerId(request.getRequestInfo().getFIConsumerId());
        consumerAccountInfoType.setFIShortName(financialInstitutionDao.getFIByIdentification(request.getRequestInfo().getFIId()).getShortName());
        consumerAccountInfoType.setFIId(request.getRequestInfo().getFIId());
        response.setConsumerInfo(consumerAccountInfoType);


        responseListener.onMessageResponse(response);

    }

    public void setDistributorDao(DistributorDao distributorDao) {
        this.distributorDao = distributorDao;
    }

    public void setMerchantDao(MerchantDao merchantDao) {
        this.merchantDao = merchantDao;
    }

    public void setFinancialInstitutionDao(FinancialInstitutionDao financialInstitutionDao) {
        this.financialInstitutionDao = financialInstitutionDao;
    }
    
    public void setZappConsumerUserDao(ZappConsumerUserDao zappConsumerUserDao) {
        this.zappConsumerUserDao = zappConsumerUserDao;
    }

}
